/**
 * This script contains tests for the FlyTED Sparql Endpoint.
 * @author Alistair Miles
 * @author Jun Zhao
 */
// convenience variables
var Assert = YAHOO.util.Assert;
var log = YAHOO.log;
var JSON = YAHOO.lang.JSON;

var sparqlns = "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n";
sparqlns += "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n";
sparqlns += "PREFIX xs: <http://www.w3.org/2001/XMLSchema#> \n";
sparqlns += "PREFIX : <http://purl.org/NET/flyatlas/schema#> \n";

var _tests = [
	
   	{   name: "test has data", 
    	query:  "ASK { ?s ?p ?o . }",
        expect: true,
    	message:"endpoint has no data"
    },
    {   name: "test has probedata", 
        query:  "ASK { ?s a :ProbeData . }",
        expect: true,
        message:"endpoint has no instances of :ProbeData"
    },
    {   name: "test has tissuevals", 
        query:  "ASK { ?s a :TissueVals . }",
        expect: true,
        message:"endpoint has no instances of :TissueVals"
    },
    {   name: "test has probedata with all props", 
        query:  "ASK { \n" +
        		"?s a :ProbeData ;\n" +
        		" :affy_id ?affy_id ;\n" +
        		" :fly_mean ?fly_mean ;\n" +
        		" :fly_SEM ?fly_SEM ;\n" +
        		" :fly_present ?fly_present ;\n" +
        		" :brain ?brain ;\n" +
        		" :head ?head ;\n" +
        		" :crop ?crop ;\n" +
        		" :midgut ?midgut ;\n" +
        		" :hindgut ?hindgut ;\n" +
        		" :tubule ?tubule ;\n" +
        		" :ovary ?ovary ;\n" +
        		" :testis ?testis ;\n" +
        		" :acc ?acc ;\n" +
        		" :l_tubule ?l_tubule ;\n" +
        		" :l_fatbody ?l_fatbody ;\n" +
        		" :ta_ganglion ?ta_ganglion ;\n" +
        		" :carcass ?carcass ;\n" +
        		" :sgland ?sgland ;\n" +
        		". \n" +
        		"}",
        expect: true,
        message:"endpoint has no instances of :ProbeData with all expected props"
    },
    {   name: "test has tissuevals with all props", 
        query:  "ASK { \n" +
        		"?s a :TissueVals ;\n" +
        		" :tissue_type ?tissue_type ;\n" +
        		" :t_change ?t_change ;\n" +
        		" :mean ?mean ;\n" +
        		" :sem ?sem ;\n" +
        		" :present ?present ;\n" +
        		" :ratio ?ratio ;\n" +
        		". }",
        expect: true,
        message:"endpoint has no instances of :TissueVals with all expected properties"
    },
    {   name: "test probedata spike cardinality", 
        query:  "ASK { \n" +
                "?s a :ProbeData ;\n" +
                " :affy_id ?affy_id_1 , ?affy_id_2 ;\n" +
                " :fly_mean ?fly_mean_1 , ?fly_mean_2 ;\n" +
                " :fly_SEM ?fly_SEM_1 , ?fly_SEM_2 ;\n" +
                " :fly_present ?fly_present_1 , ?fly_present_2 ;\n" +
                " :brain ?brain_1 , ?brain_2 ;\n" +
                " :head ?head_1 , ?head_2 ;\n" +
                " :crop ?crop_1 , ?crop_2 ;\n" +
                " :midgut ?midgut_1 , ?midgut_2 ;\n" +
                " :hindgut ?hindgut_1 , ?hindgut_2 ;\n" +
                " :tubule ?tubule_1 , ?tubule_2 ;\n" +
                " :ovary ?ovary_1 , ?ovary_2 ;\n" +
                " :testis ?testis_1 , ?testis_2 ;\n" +
                " :acc ?acc_1 , ?acc_2 ;\n" +
                " :l_tubule ?l_tubule_1 , ?l_tubule_2 ;\n" +
                " :l_fatbody ?l_fatbody_1 , ?l_fatbody_2 ;\n" +
                " :ta_ganglion ?ta_ganglion_1 , ?ta_ganglion_2 ;\n" +
                " :carcass ?carcass_1 , ?carcass_2 ;\n" +
                " :sgland ?sgland_1 , ?sgland_2 ;\n" +
                ". \n" +
                "}",
        expect: true,
        message:"cardinality spike failed"
    },
    {   name: "test tissuevals spike cardinality", 
        query:  "ASK { \n" +
                "?s a :TissueVals ;\n" +
                " :tissue_type ?tissue_type_1 , ?tissue_type_2 ;\n" +
                " :t_change ?t_change_1 , ?t_change_2 ;\n" +
                " :mean ?mean_1 , ?mean_2 ;\n" +
                " :sem ?sem_1 , ?sem_2 ;\n" +
                " :present ?present_1 , ?present_2 ;\n" +
                " :ratio ?ratio_1 , ?ratio_2 ;\n" +
                ". }",
        expect: true,
        message:"cardinality spike failed"
    },
    {   name: "test has no tissuevals with >1 for any expected =1 prop", 
        query:  "ASK { \n" +
                "?s a :TissueVals ;\n" +
                " :tissue_type ?tissue_type_1 , ?tissue_type_2 ;\n" +
                " :t_change ?t_change_1 , ?t_change_2 ;\n" +
                " :mean ?mean_1 , ?mean_2 ;\n" +
                " :sem ?sem_1 , ?sem_2 ;\n" +
                " :present ?present_1 , ?present_2 ;\n" +
                " :ratio ?ratio_1 , ?ratio_2 .\n" +
                "FILTER ( \n" +
                " ?tissue_type_1 != ?tissue_type_2 || \n" +
                " ?t_change_1 != ?t_change_2 || \n" +
                " ?mean_1 != ?mean_2 || \n" +
                " ?sem_1 != ?sem_2 || \n" +
                " ?present_1 != ?present_2 || \n" +
                " ?ratio_1 != ?ratio_2 \n" +
                ") \n" +
                "}",
        expect: false,
        message:"found >1 for some expected prop =1"
    },
    {   name: "test has no probedata with >1 for any expected =1 prop", 
        query:  "ASK { \n" +
                "?s a :ProbeData ;\n" +
                " :affy_id ?affy_id_1 , ?affy_id_2 ;\n" +
                " :fly_mean ?fly_mean_1 , ?fly_mean_2 ;\n" +
                " :fly_SEM ?fly_SEM_1 , ?fly_SEM_2 ;\n" +
                " :fly_present ?fly_present_1 , ?fly_present_2 ;\n" +
                " :brain ?brain_1 , ?brain_2 ;\n" +
                " :head ?head_1 , ?head_2 ;\n" +
                " :crop ?crop_1 , ?crop_2 ;\n" +
                " :midgut ?midgut_1 , ?midgut_2 ;\n" +
                " :hindgut ?hindgut_1 , ?hindgut_2 ;\n" +
                " :tubule ?tubule_1 , ?tubule_2 ;\n" +
                " :ovary ?ovary_1 , ?ovary_2 ;\n" +
                " :testis ?testis_1 , ?testis_2 ;\n" +
                " :acc ?acc_1 , ?acc_2 ;\n" +
                " :l_tubule ?l_tubule_1 , ?l_tubule_2 ;\n" +
                " :l_fatbody ?l_fatbody_1 , ?l_fatbody_2 ;\n" +
                " :ta_ganglion ?ta_ganglion_1 , ?ta_ganglion_2 ;\n" +
                " :carcass ?carcass_1 , ?carcass_2 ;\n" +
                " :sgland ?sgland_1 , ?sgland_2 ;\n" +
                ". \n" +
                "FILTER ( \n" +
                " ?affy_id_1 != ?affy_id_2 || \n" +
                " ?fly_mean_1 != ?fly_mean_2 || \n" +
                " ?fly_SEM_1 != ?fly_SEM_2 || \n" +
                " ?fly_present_1 != ?fly_present_2 || \n" +
                " ?brain_1 != ?brain_2 || \n" +
                " ?head_1 != ?head_2 || \n" +
                " ?crop_1 != ?crop_2 || \n" +
                " ?midgut_1 != ?midgut_2 || \n" +
                " ?hindgut_1 != ?hindgut_2 || \n" +
                " ?tubule_1 != ?tubule_2 || \n" +
                " ?ovary_1 != ?ovary_2 || \n" +
                " ?testis_1 != ?testis_2 || \n" +
                " ?acc_1 != ?acc_2 || \n" +
                " ?l_tubule_1 != ?l_tubule_2 || \n" +
                " ?l_fatbody_1 != ?l_fatbody_2 || \n" +
                " ?ta_ganglion_1 != ?ta_ganglion_2 || \n" +
                " ?carcass_1 != ?carcass_2 || \n" +
                " ?sgland_1 != ?sgland_2 \n" +
                ") \n" +
                "}",
        expect: false,
        message:"found probedata with >1 for some expected =1 prop"
    },
    {   name: "test has no probedata without affy id", 
        query:  "ASK { \n" +
                "?s a :ProbeData . \n" +
                "OPTIONAL { ?s :affy_id ?affy_id } \n" +
                "FILTER ( !bound( ?affy_id ) ) \n" +
                "}",
        expect: false,
        message:"endpoint has instances of :ProbeData without :affy_id"
    },
    {   name: "test has no probedata without required props", 
        query:  "ASK { \n" +
                "?s a :ProbeData . \n" +
                "OPTIONAL { ?s :affy_id ?affy_id } \n" +
                "OPTIONAL { ?s :fly_mean ?fly_mean } \n" +
                "OPTIONAL { ?s :fly_SEM ?fly_SEM } \n" +
                "OPTIONAL { ?s :fly_present ?fly_present } \n" +
                "OPTIONAL { ?s :brain ?brain } \n" +
                "OPTIONAL { ?s :head ?head } \n" +
                "OPTIONAL { ?s :crop ?crop } \n" +
                "OPTIONAL { ?s :midgut ?midgut } \n" +
                "OPTIONAL { ?s :hindgut ?hindgut } \n" +
                "OPTIONAL { ?s :tubule ?tubule } \n" +
                "OPTIONAL { ?s :ovary ?ovary } \n" +
                "OPTIONAL { ?s :testis ?testis } \n" +
                "OPTIONAL { ?s :acc ?acc } \n" +
                "OPTIONAL { ?s :l_tubule ?l_tubule } \n" +
                "OPTIONAL { ?s :l_fatbody ?l_fatbody } \n" +
                "OPTIONAL { ?s :ta_ganglion ?ta_ganglion } \n" +
                "OPTIONAL { ?s :carcass ?carcass } \n" +
                "OPTIONAL { ?s :sgland ?sgland } \n" +
                "FILTER ( \n" +
                "   !bound(?affy_id) || \n" +
                "   !bound(?fly_mean) || \n" +
                "   !bound(?fly_SEM) || \n" +
                "   !bound(?fly_present) || \n" +
                "   !bound(?brain) || \n" +
                "   !bound(?head) || \n" +
                "   !bound(?crop) || \n" +
                "   !bound(?midgut) || \n" +
                "   !bound(?hindgut) || \n" +
                "   !bound(?tubule) || \n" +
                "   !bound(?ovary) || \n" +
                "   !bound(?testis) || \n" +
                "   !bound(?acc) || \n" +
                "   !bound(?l_tubule) || \n" +
                "   !bound(?l_fatbody) || \n" +
                "   !bound(?ta_ganglion) || \n" +
                "   !bound(?carcass) || \n" +
                "   !bound(?sgland) \n" +
                ")\n" +
                "}",
        expect: false,
        message:"endpoint has instances of :ProbeData without some required props"
    },
    {   name: "test has no tissuevals without required props", 
        query:  "ASK { \n" +
                "?s a :TissueVals . \n" +
                "OPTIONAL { ?s :tissue_type ?tissue_type } \n" +
                "OPTIONAL { ?s :t_change ?t_change } \n" +
                "OPTIONAL { ?s :mean ?mean } \n" +
                "OPTIONAL { ?s :sem ?sem } \n" +
                "OPTIONAL { ?s :present ?present } \n" +
                "OPTIONAL { ?s :ratio ?ratio } \n" +
                "FILTER ( \n" +
                "   !bound(?tissue_type) || \n" +
                "   !bound(?t_change) || \n" +
                "   !bound(?mean) || \n" +
                "   !bound(?sem) || \n" +
                "   !bound(?present) || \n" +
                "   !bound(?ratio) \n" +
                ")\n" +
                ". }",
        expect: false,
        message:"endpoint has instances of :TissueVals without some required properties"
    },
    {   name: "test has probe to gene links", 
        query:  "ASK { \n" +
                "?probe :gene ?gene\n" +
                "}",
        expect: true,
        message:"expected probe to gene links, found none"
    },
    {   name: "test has probe to gene links: 1622973_at -> FBgn0038110 /// FBgn0068230", 
        query:  "ASK { \n" +
                "<http://openflydata.org/id/flyatlas/affyid/1622973_at> :gene <http://openflydata.org/id/flybase/feature/FBgn0038110> , <http://openflydata.org/id/flybase/feature/FBgn0068230> .\n" +
                "}",
        expect: true,
        message:"expected 1622973_at -> FBgn0038110 /// FBgn0068230"
    },
    {   name: "test has probe to gene links: 1622956_at -> FBgn0051542", 
        query:  "ASK { \n" +
                "<http://openflydata.org/id/flyatlas/affyid/1622956_at> :gene <http://openflydata.org/id/flybase/feature/FBgn0051542> .\n" +
                "}",
        expect: true,
        message:"expected 1622956_at -> FBgn0051542"
    },
    {   name: "test has probe to gene links: 1622967_at -> none", 
        query:  "ASK { \n" +
                "<http://openflydata.org/id/flyatlas/affyid/1622967_at> :gene ?gene .\n" +
                "}",
        expect: false,
        message:"expected 1622967_at -> none"
    }
          
];

var _testCase = {
	name: "FlyAtlas SPARQL Endpoint Test Case"
};


// test endpoint exists
_testCase.testEndpointExists = function() {

	// define the callback object
	var callback = {
		success: testEndpointExistsResponseSuccess(this),
		failure: testEndpointExistsResponseFailure(this)
	};
	
	log("Make the request");
	var request = YAHOO.util.Connect.asyncRequest("GET", "flyatlas", callback, null);
	
	log("Suspend the test runner");
	this.wait();
	
	log("N.B. this code should never be reached.");
}

function buildTestCase() {
	// add ask query tests to testcase object
	for (var i=0; i<_tests.length; i++) {
	    var _test = _tests[i];
        log("adding test "+_test.name+" to testcase, query is: "+_test.query);
	    _testCase[_test.name] = buildTestFunction(_test.name, _test.query, _test.expect, _test.message);
	}
}

// pause between tests to avoid tripping mod_evasive
var pause = 500;

function buildTestFunction(testname, query, expect, message) {
	return function() {
        log("test: "+testname);
        var _query = sparqlns + query;
        _query = _query.replace(/</g,"&lt;").replace(/>/g,"&gt;");
        var e_query = document.getElementById("query");
        if (e_query.textContent) {
        	e_query.textContent = _query;
        } else {
        	e_query.innerText = _query;
        }
//        document.getElementById("query").textContent = _query;
//        log("spike innerText: "+document.getElementById("query").innerText);
        var tc = this;
        tc.wait(function() {
//	        document.getElementById("query").innerHTML = query;
        	testAskQuery("flyatlas", tc, query, expect, message);
       	}, pause);
	}
}

function setup() {
	var logReader = new YAHOO.tool.TestLogger("logger");
	YAHOO.log("Logger setup done");	
	buildTestCase();
	YAHOO.log("populate select...");
	var select = document.getElementById("selecttest");
	select.innerHTML = "";
//	var inner = ""
	for (var i=0; i<_tests.length; i++) {
		var _test = _tests[i];
		var option = document.createElement("option");
		option.innerHTML = _test.name;
		select.appendChild(option);
//	    inner += "<option>"+_testname+"</option>";
	}
//	YAHOO.log("generated inner content: "+inner);
//	document.getElementById("selecttest").innerHTML = inner;
}

function runTests() {
    document.getElementById("query").innerHTML = "";
	YAHOO.log("Running tests");
	YAHOO.tool.TestRunner.clear();
	YAHOO.tool.TestRunner.add(new YAHOO.tool.TestCase(_testCase));
	YAHOO.tool.TestRunner.run();
}

function runTest(index) {
	YAHOO.log("runTest: "+index);
    var test = _tests[index];
    YAHOO.log("found test: "+test.message);
    var testCase = {name: "FlyAtlas SPARQL Endpoint Test Case: "+test.name};
    if (typeof test != "undefined" || test) {
//        var query = sparqlns + test.query;
//        query = query.replace(/</g,"&lt;").replace(/>/g,"&gt;");
//        document.getElementById("query").innerHTML = query;
        testCase[test.name] = buildTestFunction(test.name, test.query, test.expect, test.message);
        YAHOO.log("Running tests");
        YAHOO.tool.TestRunner.clear();
        YAHOO.tool.TestRunner.add(new YAHOO.tool.TestCase(testCase));
        YAHOO.tool.TestRunner.run();
    } else {
        YAHOO.log("test not found", "error");
    }
//	var _test = _tests[testName];
//	if (typeof _test != "undefined" || _test) {
//		var to = {
//			name : testName
//		};
//		var fn = function() {
//			testAskQuery("flybase", this, _test.query, _test.expect, _test.message);
//		};
//		to[testName] = fn;
//		var testCase = new YAHOO.tool.TestCase(to);
//		YAHOO.tool.TestRunner.clear();
//		YAHOO.tool.TestRunner.add(testCase);
//		YAHOO.tool.TestRunner.run();
//	}
}

function runSelected() {
    var value = document.getElementById("selecttest").value;
    log("select value: "+value);
	var index = document.getElementById("selecttest").selectedIndex;
	log("select index: "+index)
    runTest(index);
}

YAHOO.util.Event.onDOMReady(setup);
//YAHOO.util.Event.onDOMReady(runTests);

